#pragma once

#define MAX_LENGTH_OF_PROMPT_STRING 128

#define ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0]))


typedef enum return_value_enum {
    OK_RETURN,
    ERROR_RETURN,
    WARRING_RETURN,
    FATAL_ERROR_RETURN
} return_value_enum_t;


typedef enum {
    ITEM_TYPE,
    FOLDER_TYPE
} node_type_enum_t;


typedef struct menu_node_s {
    char prompt[MAX_LENGTH_OF_PROMPT_STRING];
    node_type_enum_t node_type;
    unsigned int sub_node_number;

    union {
        void (*func)(void);
        struct menu_node_s *sub_node_list;
    } node_value;
} menu_node_t;


#define FOLDER_NODE_INITIALIZER(prompt_str, sub_nodes...) \
{ \
    .prompt = prompt_str, \
    .node_type = FOLDER_TYPE, \
    .sub_node_number = ARRAY_LENGTH(((menu_node_t []) sub_nodes)), \
    .node_value.sub_node_list = (menu_node_t []) sub_nodes \
}


#define ITEM_NODE_INITIALIZER(prompt_str, function) \
{ \
    .prompt = prompt_str, \
    .node_type = ITEM_TYPE, \
    .node_value.func = function \
}


return_value_enum_t ShowMenu(menu_node_t *menu_root);